package cn.vic.genertor.view;

import cn.vic.config.ConfigStatic;
import cn.vic.config.Configuration;
import cn.vic.config.TypeMapping;
import cn.vic.config.model.DatabaseElement;
import cn.vic.db.Database;
import cn.vic.db.DatabaseFactory;
import cn.vic.db.model.Column;
import cn.vic.db.model.Table;
import cn.vic.enums.ViewTypeEnum;
import cn.vic.exception.ApplicationException;
import cn.vic.genertor.other.JsonToMarkDown;
import cn.vic.genertor.view.ui.TreeNodeData;
import cn.vic.genertor.view.ui.component.ComboBoxEditor;
import cn.vic.genertor.view.ui.component.EditableTable;
import cn.vic.model.TableUpdateModel;
import cn.vic.util.*;
import org.apache.log4j.Logger;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.plaf.FontUIResource;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.List;
import java.util.Map.Entry;


public class Root extends JFrame {

    private static final Logger LOGGER = Logger.getLogger(Root.class);

    private static final long serialVersionUID = -7813705897974255551L;

    private static Font FONT_YAHEI = new Font("微软雅黑", Font.PLAIN, 12);

    private String[] headers = {"字段名", "字段类型", "JAVA类型", "大小", "主键", "唯一", "自增", "外键",
            "可空", "默认值", "显示", "搜索", "编辑", "排序", "数据字典", "注释"};
    private int[] headerWidth = {120, 80, 80, 50, 30, 30, 30, 30, 30, 50, 30, 30, 30, 30, 100, 150};
    public static final int IDX_COLUMN_JAVATYPE = 2;
    public static final int IDX_COLUMN_NULLABLE = 8;
    public static final int IDX_COLUMN_DISPLAY = 10;
    public static final int IDX_COLUMN_SEARCHABLE = 11;
    public static final int IDX_COLUMN_EDITOR = 12;
    public static final int IDX_COLUMN_SORTABLE = 13;
    public static final int IDX_COLUMN_DICT = 14;
    public static final int IDX_COLUMN_REMARK = 15;

    private JPanel contentPane;
    private JSplitPane contentSplitPane;

    private DefaultTreeModel tablesTreeModel;
    private JTree tablesTree;

    private ImageIcon icon = ImageUtil.createImageIcon("icon/Guy-Fawkes-Mask.png");

    private JScrollPane rightScrollPane;
    private EditableTable tableGrid;
    private DefaultTableModel tableGridModel;

    //修改后保存在这里
    //库.表.字段 KEY
    private Map<String, TableUpdateModel> tableChangedMap = new HashMap();
    private DatabaseElement lastDatabaseElement;
    /**
     * 菜单集合
     */
    private Map<String, JPopupMenu> menuMap = new HashMap<>();

    private JSplitPane rightSplitPane;
    private JPanel rightTopPanel;
    private JButton btnGenerate;

    private Configuration configuration;
    private TypeMapping typeMapping;

    private Table tableModel;
    private String classPath;
    private String treeSearch;

    /**
     * Create the frame.
     */
    public Root() {
        setTitle("AutoCodeGenerator");
        setIconImage(icon.getImage());
        //右上角X 按钮事件
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                shutdown();
            }
        });
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        setWindowsWidthHeight();

        JMenuBar menuBar = new JMenuBar();
        this.setJMenuBar(menuBar);

        //菜单栏
        JMenu mnNewMenu = new JMenu("File");
        mnNewMenu.setFont(FONT_YAHEI);
        menuBar.add(mnNewMenu);
        //连接管理
        JMenuItem mntmConnect = new JMenuItem("连接管理");
        mntmConnect.setIcon(ImageUtil.createImageIcon("icon/link.png"));
        mntmConnect.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                onConnectActionPerformed();
            }
        });
        mntmConnect.setFont(FONT_YAHEI);
        mnNewMenu.add(mntmConnect);
        //关闭连接
        JMenuItem mntmDisconnect = new JMenuItem("关闭所有连接");
        mntmDisconnect.setIcon(ImageUtil.createImageIcon("icon/closed.png"));
        mntmDisconnect.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                disConnection();
            }
        });
        mntmDisconnect.setFont(FONT_YAHEI);
        mnNewMenu.add(mntmDisconnect);

        JMenuItem configItem = new JMenuItem("设置");
        configItem.setFont(FONT_YAHEI);
        configItem.setIcon(ImageUtil.createImageIcon("icon/config.png"));
        configItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                ConfigView view = new ConfigView(Root.this, true, configuration);
                view.setVisible(true);
            }
        });
        mnNewMenu.add(configItem);


        //显示sql按钮
        JMenuItem showSql = new JMenuItem("显示Sql");
        showSql.setFont(FONT_YAHEI);
        showSql.setIcon(ImageUtil.createImageIcon("icon/eye.png"));
        showSql.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                ShowSqlView sqlView = new ShowSqlView(Root.this, true, tableChangedMap);
                sqlView.setVisible(true);
            }
        });
        mnNewMenu.add(showSql);
        //菜单栏 退出按钮
        JMenuItem menuItemExit = new JMenuItem("Exit");
        menuItemExit.setFont(FONT_YAHEI);
        menuItemExit.setIcon(ImageUtil.createImageIcon("icon/logout.png"));
        menuItemExit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                onExitActionPerformed();
            }
        });

        mnNewMenu.add(menuItemExit);
        //mnNewMenu.addSeparator();

        //工具类菜单
        JMenu menuTools = new JMenu("Tools");
        menuTools.setFont(FONT_YAHEI);
        menuBar.add(menuTools);

        JMenuItem jsonToMarkDownItem = new JMenuItem("JsonToMarkDown");
        jsonToMarkDownItem.setFont(FONT_YAHEI);
        jsonToMarkDownItem.setIcon(ImageUtil.createImageIcon("icon/exchange.png"));
        jsonToMarkDownItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JsonToMarkDown down = new JsonToMarkDown(Root.this);
                down.setVisible(true);
            }
        });
        menuTools.add(jsonToMarkDownItem);
        //menuTools.addSeparator();

        //初始化左右边框，异步调用
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                //初始化配置
                initSettings();
                //拆分pane 区域
                contentPane = new JPanel();
                contentPane.setFont(FONT_YAHEI);
                contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
                contentPane.setLayout(new BorderLayout(0, 0));
                setContentPane(contentPane);
                contentSplitPane = new JSplitPane();
                contentSplitPane.setFont(FONT_YAHEI);
                contentSplitPane.setDividerSize(6);
                contentSplitPane.setDividerLocation(350);
                contentPane.add(contentSplitPane, BorderLayout.CENTER);
                //初始化左边
                contentSplitPane.setLeftComponent(buildLeftPane());
                //初始化左边右键菜单
                initLeftMenu();

                rightSplitPane = new JSplitPane();
                rightSplitPane.setFont(FONT_YAHEI);
                rightSplitPane.setBorder(new EmptyBorder(0, 0, 0, 0));
                rightSplitPane.setDividerSize(6);
                rightSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
                rightSplitPane.setDividerLocation(30);
                rightSplitPane.setEnabled(false);
                contentSplitPane.setRightComponent(rightSplitPane);

                rightScrollPane = new JScrollPane();
                rightScrollPane.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
                rightSplitPane.setBottomComponent(rightScrollPane);

                tableGrid = new EditableTable();
                rightScrollPane.setViewportView(tableGrid);

                rightTopPanel = new JPanel();
                rightTopPanel.setAlignmentY(0.0f);
                rightTopPanel.setAlignmentX(0.0f);
                rightTopPanel.setBorder(new EmptyBorder(0, 0, 0, 0));
                rightTopPanel.setPreferredSize(new Dimension(300, 100));
                rightSplitPane.setTopComponent(rightTopPanel);
                rightTopPanel.setLayout(new BorderLayout(0, 0));

                btnGenerate = new JButton("生成...");
                btnGenerate.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        onGenerateActionPerformed();
                    }
                });
                btnGenerate.setEnabled(false);
                rightTopPanel.add(btnGenerate);
                //设置全局字体
                initGlobalFont(FONT_YAHEI);
                //初始化表格
                drawTableGrid();
            }
        });


    }

    /**
     * 搜索tree
     *
     * @param root
     * @param str
     */
    private void findInTree(DefaultMutableTreeNode root, String str) {
        //判断上次和这次的搜索条件是否一致
        if (treeSearch != null && treeSearch.equals(str)) {
            return;
        }
        treeSearch = str;
        List<TreePath> selectionPath = new ArrayList<>();
        //收回 折叠
        //tablesTree.expandPath(new TreePath(root.getLastChild()));
        //下拉定位 或者隐藏
        //清理选中
        tablesTree.setSelectionPaths(new TreePath[0]);
        if (StringUtils.isBlank(str)) {
            return;
        }
        findInPath(root, str, selectionPath);
        if (selectionPath != null && selectionPath.size() > 0) {
            TreePath[] treePaths = new TreePath[selectionPath.size()];
            selectionPath.toArray(treePaths);
            tablesTree.expandPath(treePaths[0]); //展开路径.
            tablesTree.setSelectionPaths(treePaths);


            //tablesTree.scrollPathToVisible(treePaths[0]);
        }
    }


    private void findInPath(DefaultMutableTreeNode root, String str, List<TreePath> selectionPath) {
        if (root == null) {
            return;
        }
        String value = root.toString();
        if (value.toUpperCase().indexOf(str.toUpperCase()) > -1) {
            //TreePath treePath = new TreePath(root);
            TreePath treePath = new TreePath(root.getPath()); //定义路径变量.
            selectionPath.add(treePath);
        }
        int count = root.getChildCount();
        if (count > 0) {
            for (int i = 0; i < count; i++) {
                DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) root.getChildAt(i);
                findInPath(treeNode, str, selectionPath);
            }
        }
    }


    /**
     * 初始化右键菜单
     */
    private void initLeftMenu() {
        /*******************HostMenu*************************/
        JPopupMenu hostMenu = new JPopupMenu();
        JMenuItem openItemInfo = new JMenuItem("打开连接");
        openItemInfo.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                loadDatabaseTable();
            }
        });
        hostMenu.add(openItemInfo);

        JMenuItem refreshItemInfo = new JMenuItem("刷新");
        refreshItemInfo.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                closeNodeConnect(true);
                loadDatabaseTable();
            }
        });
        hostMenu.add(refreshItemInfo);

        JMenuItem closeItemInfo = new JMenuItem("关闭连接");
        closeItemInfo.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                closeNodeConnect(true);
            }
        });
        hostMenu.add(closeItemInfo);
        menuMap.put("hostMenu", hostMenu);

        /***************DataBaseMenu*****************************/
        JPopupMenu dataBaseMenu = new JPopupMenu();
        JMenuItem itemInfo = new JMenuItem("获取表信息");
        itemInfo.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                loadDatabaseTable();
            }
        });
        dataBaseMenu.add(itemInfo);

        JMenuItem reItemInfo = new JMenuItem("刷新");
        reItemInfo.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                closeNodeConnect(true);
                loadDatabaseTable();
            }
        });
        dataBaseMenu.add(reItemInfo);

        closeItemInfo = new JMenuItem("关闭连接");
        closeItemInfo.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                closeNodeConnect(false);
            }
        });
        dataBaseMenu.add(closeItemInfo);
        menuMap.put("dataBaseMenu", dataBaseMenu);

        /****************TableMenu****************************/
        // 选中TABLE 右键菜单

        JPopupMenu tableMenu = new JPopupMenu();

        JMenuItem openTableItem = new JMenuItem("预览");
        openTableItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                loadDatabaseTable();
            }
        });
        tableMenu.add(openTableItem);

        JMenuItem tableItem = new JMenuItem("生成代码");
        tableItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                onMultiselectCodeGeneration();
            }
        });
        tableMenu.add(tableItem);
        menuMap.put("tableMenu", tableMenu);

    }


    /**
     * 关闭连接
     *
     * @param flag true 关闭连接  false 不关闭
     */
    private void closeNodeConnect(boolean flag) {
        TreePath[] selectionPaths = tablesTree.getSelectionPaths();
        DefaultMutableTreeNode treeNode = null;
        for (TreePath treePath : selectionPaths) {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent();
            treeNode = node;
            TreeNodeData nodeData = (TreeNodeData) node.getUserObject();
            if (flag) {
                if ("HOST".equals(nodeData.getType())) {
                    nodeData.getDatabaseElement().allClose();
                } else if ("DATABASE".equals(nodeData.getType())) {
                    nodeData.getDatabaseElement().close(nodeData.getText());
                }
            }
            node.removeAllChildren();
        }
        if (treeNode != null) {
            tablesTreeModel.reload();
            if (!treeNode.getParent().isLeaf()) {
                DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode) treeNode.getParent();
                //判断该节点的路径.
                TreePath path = new TreePath(defaultMutableTreeNode.getPath()); //定义路径变量.
                tablesTree.expandPath(path); //展开路径.
                tablesTree.setSelectionPath(new TreePath(treeNode.getPath())); //选中
            }
        }
    }

    /**
     * 初始化左边
     *
     * @return
     */
    private JPanel buildLeftPane() {
        JPanel leftPane = new JPanel(new BorderLayout());
        leftPane.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));

        initTableTree();
        final JScrollPane treePane = new JScrollPane(tablesTree);
        treePane.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
        leftPane.add(treePane, BorderLayout.CENTER);

        //  表名搜索框，根据输入的表名，在tree中选择第一个匹配的表名
        JTextField tableSearchField = new JTextField("");
        leftPane.add(tableSearchField, BorderLayout.NORTH);
        tableSearchField.addCaretListener(new CaretListener() {
            @Override
            public void caretUpdate(CaretEvent e) {
                JTextField field = (JTextField) e.getSource();
                String text = field.getText();
                //if (text == null || text.length() == 0 || tablesTreeModel.getRoot() == null) return;
                //text = text.toLowerCase();
                //  search table names
                DefaultMutableTreeNode root = (DefaultMutableTreeNode) tablesTreeModel.getRoot();
                //TODO 暂时没有找到很好的方式   用于隐藏
                findInTree(root, text);
            }
        });
        return leftPane;
    }

    /**
     * 初始化左侧表和视图的树形结构
     */
    private void initTableTree() {
        TreeNodeData nodeData = new TreeNodeData("root", ViewTypeEnum.FOLADER.getImageIcon(), "");
        DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(nodeData);
        List<DatabaseElement> databaseElementList = configuration.getConnectionHistory();
        for (DatabaseElement database : databaseElementList) {
            TreeNodeData hostNodeData = new TreeNodeData(database.getName(), ViewTypeEnum.HOST, database);
            DefaultMutableTreeNode hostNode = new DefaultMutableTreeNode(hostNodeData);
            rootNode.add(hostNode);
        }

        tablesTreeModel = new DefaultTreeModel(rootNode);

        tablesTree = new JTree(tablesTreeModel);
        tablesTree.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseReleased(MouseEvent e) {
                onTablesTreeMouseReleased(e);
            }

            @Override
            public void mousePressed(MouseEvent e) {
                onTablesTreeMousePressed(e);
            }
        });
        tablesTree.setRootVisible(false);
        tablesTree.setShowsRootHandles(true);
        tablesTree.setCellRenderer(new GridCellRenderer());
    }

    /**
     * 刷新左侧表和视图的树形结构
     */
    private void refreshTableTree() {
        Map<String, DatabaseElement> databaseMap = new HashMap<>();
        List<DatabaseElement> databaseElementList = configuration.getConnectionHistory();
        for (DatabaseElement database : databaseElementList) {
            databaseMap.put(database.getName(), database);
        }
        DefaultMutableTreeNode root = (DefaultMutableTreeNode) tablesTreeModel.getRoot();
        for (int i = 0; i < root.getChildCount(); i++) {
            DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) root.getChildAt(i);
            TreeNodeData userObject = (TreeNodeData) childNode.getUserObject();
            if (!databaseMap.containsKey(userObject.getText())) { //找不到就删除。
                root.remove(i);
                childNode.removeFromParent();
            }
        }

        Map<String, DefaultMutableTreeNode> treeNodeMap = new HashMap<>();
        for (int i = 0; i < root.getChildCount(); i++) {
            DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) root.getChildAt(i);

            TreeNodeData userObject = (TreeNodeData) childNode.getUserObject();
            treeNodeMap.put(userObject.getText(), childNode);
        }
        for (DatabaseElement database : databaseElementList) {
            if (!treeNodeMap.containsKey(database.getName())) { //找不到就添加
                TreeNodeData hostNodeData = new TreeNodeData(database.getName(), ViewTypeEnum.HOST, database);
                DefaultMutableTreeNode hostNode = new DefaultMutableTreeNode(hostNodeData);
                root.add(hostNode);
            }
        }
        //获取选中得节点，进行展开，这里获取不到没有选中并展开得节点。
        TreePath[] selectionPaths = tablesTree.getSelectionPaths();
        tablesTreeModel.reload();
        //closeNodeConnect
        if (selectionPaths != null && selectionPaths.length > 0) {
            for (TreePath deTree : selectionPaths) {
                TreePath path = new TreePath(deTree.getPath()); //定义路径变量.
                tablesTree.expandPath(path); //展开路径.
            }
            tablesTree.setSelectionPaths(selectionPaths); //选中
        }

    }

    /**
     * 初始化配置
     * 加载jar包 及 database
     */
    private void initSettings() {
        File f = new File(getClass().getProtectionDomain().getCodeSource().getLocation().getFile());
        classPath = f.getParentFile().getPath() + File.separator;
        classPath = classPath.replaceAll("%20", " ");

        configuration = new Configuration("./");
        try {
            configuration.loadConfiguration();
            //动态加载jar包
            if (!configuration.getClassPathEntries().isEmpty()) {
                ClassLoader classLoader = ClassloaderUtility.getCustomClassloader("./", configuration.getClassPathEntries());
                ObjectFactory.addExternalClassLoader(classLoader);
            }
            ConfigStatic.put("configuration", configuration);
        } catch (Exception e) {
            LOGGER.info(e.getMessage(), e);
            JOptionPane.showMessageDialog(this, e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
        }

        typeMapping = new TypeMapping("./");
        try {
            typeMapping.loadMappgin();
        } catch (Exception e) {
            LOGGER.info(e.getMessage(), e);
            JOptionPane.showMessageDialog(this, e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    /**
     * 设置全局字体
     *
     * @param font
     */
    private static void initGlobalFont(Font font) {
        FontUIResource fontRes = new FontUIResource(font);
        for (Enumeration<Object> keys = UIManager.getDefaults().keys(); keys.hasMoreElements(); ) {
            Object key = keys.nextElement();
            Object value = UIManager.get(key);
            if (value instanceof FontUIResource) {
                UIManager.put(key, fontRes);
            }
        }
    }

    /**
     * 给主机加载表
     *
     * @param schema
     */
    private void loadTableTree(DefaultMutableTreeNode treeNode, Connection connection, String schema, String dataBase) {
        String schemaPattern = null;
        DefaultMutableTreeNode hostTablesNode = null;
        DefaultMutableTreeNode hostViewsNode = null;
        try {
            TreeNodeData hostNodeData = (TreeNodeData) treeNode.getUserObject();

            //创建表 视图节点
            TreeNodeData nodeData = new TreeNodeData("表", ViewTypeEnum.FOLADER, hostNodeData.getDatabaseElement());
            nodeData.setDataBase(dataBase);
            hostTablesNode = new DefaultMutableTreeNode(nodeData);
            treeNode.add(hostTablesNode);

            nodeData = new TreeNodeData("视图", ViewTypeEnum.FOLADER, hostNodeData.getDatabaseElement());
            nodeData.setDataBase(dataBase);
            hostViewsNode = new DefaultMutableTreeNode(nodeData);
            treeNode.add(hostViewsNode);

            hostTablesNode.removeAllChildren();
            hostViewsNode.removeAllChildren();

            if (StringUtil.isNotEmpty(schema)) {
                schemaPattern = schema;
            }
            ResultSet rs = connection.getMetaData().getTables(null, schemaPattern, "%", null);
            while (rs.next()) {
                TreeNodeData data;
                DefaultMutableTreeNode tableNode;
                String tableSchema = rs.getString(2);
                String tableName = rs.getString(3);
                if (StringUtil.isNotEmpty(tableSchema)) {
                    tableName = tableSchema + "." + tableName;
                }
                if ("VIEW".equalsIgnoreCase(rs.getString(4))) {
                    data = new TreeNodeData(tableName, ViewTypeEnum.VIEW, hostNodeData.getDatabaseElement());
                    data.setDataBase(dataBase);
                    tableNode = new DefaultMutableTreeNode(data);
                    hostViewsNode.add(tableNode);
                } else {
                    data = new TreeNodeData(tableName, ViewTypeEnum.TABLE, hostNodeData.getDatabaseElement());
                    data.setDataBase(dataBase);
                    tableNode = new DefaultMutableTreeNode(data);
                    hostTablesNode.add(tableNode);
                }
            }
            rs.close();
            tablesTreeModel.reload();
            if (!treeNode.isLeaf()) {
                //判断该节点的路径.
                TreePath path = new TreePath(treeNode.getPath()); //定义路径变量.
                tablesTree.expandPath(path); //展开路径.
            }
        } catch (SQLException e) {
            LOGGER.info(e.getMessage(), e);
            JOptionPane.showMessageDialog(this, e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
        } finally {
            try {
                if (connection != null) {
                    connection.isReadOnly();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 设置窗口 高度和宽度
     */
    public void setWindowsWidthHeight() {
        Dimension dim = getToolkit().getScreenSize();
        int width = 1130;
        int height = 710;
        int x = (dim.width - width) / 2;
        int y = (dim.height - height) / 2;
        this.setBounds(x, y, width, height);
    }

    /**
     * 关闭连接
     */

    public void disConnection() {
        DefaultMutableTreeNode root = (DefaultMutableTreeNode) tablesTreeModel.getRoot();
        for (int i = 0; i < root.getChildCount(); i++) {
            DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) root.getChildAt(i);
            TreeNodeData nodeData = (TreeNodeData) treeNode.getUserObject();
            if (nodeData.getDatabaseElement() != null) {
                nodeData.getDatabaseElement().allClose();
            }
            treeNode.removeAllChildren();
        }
        tablesTreeModel.reload();
    }

    /**
     * 关闭软件 一些操作
     * //TODO 需要在这里加入清除table操作
     */
    private void shutdown() {
        disConnection();
        dispose();
    }

    /**
     * 连接管理 dialog 打开方法
     */
    private void onConnectActionPerformed() {
        DbManagementDialog dbManagementDialog = new DbManagementDialog(this, configuration);
        dbManagementDialog.setVisible(true);
        refreshTableTree();//刷新左边栏目
        configuration.save();//保存
    }

    /**
     * 关闭所有连接
     */
    private void onExitActionPerformed() {
        this.shutdown();
    }

    /**
     * 左侧 tree 点击事件
     *
     * @param evt
     */
    private void onTablesTreeMouseReleased(MouseEvent evt) {
        //判断是否为右击
        if (evt.isPopupTrigger()) {
            TreePath selPath = tablesTree.getPathForLocation(evt.getX(), evt.getY());
            if (selPath == null || selPath.getPath() == null) {
                return;
            }
            //判断点击对象是否在选中对象中，如果没有给选中
            if (!isTreePathExistence(selPath)) {
                tablesTree.setSelectionPath(selPath);
            }
            DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) selPath.getLastPathComponent();
            TreeNodeData treeNodeData = (TreeNodeData) treeNode.getUserObject();
            if ("HOST".equals(treeNodeData.getType())) {
                if (StringUtil.isNotBlank(treeNodeData.getDatabaseElement().getDataBase())) {
                    JPopupMenu dataBaseMenu = menuMap.get("dataBaseMenu");
                    dataBaseMenu.show(evt.getComponent(), evt.getX(), evt.getY());
                } else {
                    JPopupMenu dataBaseMenu = menuMap.get("hostMenu");
                    dataBaseMenu.show(evt.getComponent(), evt.getX(), evt.getY());

                }
            } else if ("DATABASE".equals(treeNodeData.getType())) {//刷新表
                JPopupMenu dataBaseMenu = menuMap.get("dataBaseMenu");
                dataBaseMenu.show(evt.getComponent(), evt.getX(), evt.getY());
            } else if ("TABLE".equals(treeNodeData.getType())) {
                JPopupMenu tableMenu = menuMap.get("tableMenu");
                tableMenu.show(evt.getComponent(), evt.getX(), evt.getY());
            }
        }
    }

    /**
     * 判断 是否被选中
     *
     * @param selPath
     */
    private boolean isTreePathExistence(TreePath selPath) {
        for (TreePath path : tablesTree.getSelectionPaths()) {
            if (selPath.equals(path)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 多选代码生成
     */
    private void onMultiselectCodeGeneration() {
        //进行多选 生成
        TreePath[] selectionPaths = tablesTree.getSelectionPaths();
        StringBuffer tableNames = new StringBuffer();
        for (TreePath treePath : selectionPaths) {
            DefaultMutableTreeNode mutableTreeNode = (DefaultMutableTreeNode) treePath.getLastPathComponent();
            TreeNodeData treeNodeData1 = (TreeNodeData) mutableTreeNode.getUserObject();

            tableNames.append(treeNodeData1.getText()).append(";");
        }
        LoadAotuCodeViewHistory view = new LoadAotuCodeViewHistory(Root.this, configuration, tableNames.toString());
        view.setSelectionPaths(selectionPaths);
        view.setTypeMapping(typeMapping);
        view.setVisible(true);
    }

    /**
     * 左侧 tree 点击事件
     *
     * @param evt
     */
    private void onTablesTreeMousePressed(MouseEvent evt) {
        JTree j = (JTree) evt.getSource();
        //判断是否双击
        if (evt.getClickCount() == 2) {
            loadDatabaseTable();
        }
    }

    public void fitTableColumns(JTable table) {
        JTableHeader header = table.getTableHeader();
        int rowCount = table.getRowCount();
        Enumeration<TableColumn> columns = table.getColumnModel().getColumns();
        while (columns.hasMoreElements()) {
            TableColumn column = (TableColumn) columns.nextElement();
            int col = header.getColumnModel().getColumnIndex(column.getIdentifier());
            int width = (int) table.getTableHeader().getDefaultRenderer()
                    .getTableCellRendererComponent(table, column.getIdentifier(), false, false, -1, col).getPreferredSize().getWidth();
            for (int row = 0; row < rowCount; row++) {
                int preferedWidth = (int) table.getCellRenderer(row, col)
                        .getTableCellRendererComponent(table,
                                table.getValueAt(row, col), false, false, row, col).getPreferredSize().getWidth();
                width = Math.max(width, preferedWidth);
            }
            header.setResizingColumn(column); // 此行很重要
            column.setWidth(width + table.getIntercellSpacing().width);
        }
    }

    /**
     * 设置 表格宽度
     *
     * @param table
     * @param columnWidths
     */
    public void fitTableColumns(JTable table, int[] columnWidths) {
        for (int i = 0; i < columnWidths.length; i++) {
            table.getColumnModel().getColumn(i).setPreferredWidth(columnWidths[i]);
        }
    }

    /**
     * 初始化 table
     */
    private void drawTableGrid() {
        Object[][] cellData = new Object[0][headers.length];
        tableGridModel = new DefaultTableModel(cellData, headers) {
            private static final long serialVersionUID = 880033063879582590L;

            @Override
            public boolean isCellEditable(int row, int column) {
                return column == IDX_COLUMN_JAVATYPE || column == IDX_COLUMN_NULLABLE || column == IDX_COLUMN_DISPLAY
                        || column == IDX_COLUMN_SEARCHABLE || column == IDX_COLUMN_SORTABLE || column == IDX_COLUMN_EDITOR
                        || column == IDX_COLUMN_DICT || column == IDX_COLUMN_REMARK;
            }
        };
        tableGridModel.addTableModelListener(new MyTableModelListener());
        tableGrid.setModel(tableGridModel);
        tableGrid.setRowHeight(22);
        // 第2列为下拉
        tableGrid.setComboCell(IDX_COLUMN_JAVATYPE, new ComboBoxEditor(typeMapping.getAllJavaTypes()));
        //设置不拖动
        tableGrid.getTableHeader().setReorderingAllowed(false);

        fitTableColumns(tableGrid, headerWidth);
    }

    /**
     * 左边树双击 事件
     */
    private void loadDatabaseTable() {
        TreePath selPath = tablesTree.getSelectionPath();
        if (selPath == null || selPath.getPath() == null) {
            return;
        }
        DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) selPath.getLastPathComponent();
        TreeNodeData nodeData = (TreeNodeData) treeNode.getUserObject();
        try {
            if ("HOST".equals(nodeData.getType())) { //加载库
                //如果库已经加载，不进行查询
                if (treeNode.getChildCount() == 0) {
                    if (StringUtils.isNotBlank(nodeData.getDatabaseElement().getDataBase())) { //如果存在database 就直接加载
                        DatabaseElement databaseElement = nodeData.getDatabaseElement();
                        loadTableTree(treeNode, databaseElement.getConnection(), databaseElement.getSchema(), databaseElement.getDataBase());
                    } else {
                        loadDataLib(treeNode);
                    }
                }
            } else if ("DATABASE".equals(nodeData.getType())) {//加载表
                if (treeNode.getChildCount() == 0) {
                    DefaultMutableTreeNode hostNode = (DefaultMutableTreeNode) selPath.getParentPath().getLastPathComponent();
                    TreeNodeData hostNodeData = (TreeNodeData) hostNode.getUserObject();
                    DatabaseElement databaseElement = hostNodeData.getDatabaseElement();
                    loadTableTree(treeNode, databaseElement.getConnection(nodeData.getText()), databaseElement.getSchema(), nodeData.getText());
                }
            } else if ("TABLE".equals(nodeData.getType())) {//加载表字段
                DefaultMutableTreeNode selNode = (DefaultMutableTreeNode) selPath.getPath()[2];
                String dataBase = ((TreeNodeData) selNode.getUserObject()).getText(); //库名
                DefaultMutableTreeNode hostNode = (DefaultMutableTreeNode) selNode.getParent(); //地址
                DatabaseElement databaseElement = ((TreeNodeData) hostNode.getUserObject()).getDatabaseElement();
                Connection connection = StringUtils.isBlank(databaseElement.getDataBase()) ? databaseElement.getConnection(dataBase) : databaseElement.getConnection();
                lastDatabaseElement = databaseElement;
                String nodeText = ((TreeNodeData) treeNode.getUserObject()).getText(); //表
                String tableSchema = null;
                String tableName = nodeText;
                if (nodeText.indexOf(".") > 0) {
                    tableName = nodeText.substring(nodeText.indexOf(".") + 1);
                    tableSchema = nodeText.substring(0, nodeText.indexOf("."));
                }
                loadTableGridData(connection, tableSchema, tableName);
            }
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, e.getMessage(), "错误", JOptionPane.INFORMATION_MESSAGE);
        }
    }

    /**
     * 加载 连接 数据库
     *
     * @param treeNode
     */
    private void loadDataLib(DefaultMutableTreeNode treeNode) {
        Connection connection = null;
        try {
            TreeNodeData nodeData = (TreeNodeData) treeNode.getUserObject();
            connection = nodeData.getDatabaseElement().getConnection();
            treeNode.removeAllChildren();

            //show databases
            List<String> list = new ArrayList<>();
            DatabaseMetaData meta = connection.getMetaData();
            ResultSet rsTables = meta.getCatalogs();
            while (rsTables.next()) {
                list.add(String.valueOf(rsTables.getObject(1)));
            }

            for (String value : list) {
                TreeNodeData libNodeData = new TreeNodeData(value, ViewTypeEnum.DATABASE, nodeData.getDatabaseElement());
                DefaultMutableTreeNode libNode = new DefaultMutableTreeNode(libNodeData);
                treeNode.add(libNode);
            }
            tablesTreeModel.reload();
            if (!treeNode.isLeaf()) {
                //判断该节点的路径.
                TreePath path = new TreePath(treeNode.getPath()); //定义路径变量.
                tablesTree.expandPath(path); //展开路径.
            }
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(this, e.getMessage(), "提示", JOptionPane.INFORMATION_MESSAGE);
        } finally {
            try {
                if (connection != null) {
                    connection.isReadOnly();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 加载 表字段
     *
     * @param connection
     * @param tableSchema
     * @param tableName
     */
    private void loadTableGridData(Connection connection, String tableSchema, String tableName) {
        try {
            Database db = DatabaseFactory.createDatabase(connection, typeMapping);
            tableModel = db.getTable(null, tableSchema, tableName);
            if (tableModel == null) {
                String message = tableName + " 无法获取表字段,可能为数据库系统表。";
                LOGGER.info(message);
                JOptionPane.showMessageDialog(this, message, "错误", JOptionPane.ERROR_MESSAGE);
                return;
            }
            Map<String, Column> columnMap = new LinkedHashMap<String, Column>();
            List<Column> keyCols = tableModel.getPrimaryKeys();
            for (Column col : keyCols) {
                columnMap.put(col.getColumnName(), col);
            }
            List<Column> baseCols = tableModel.getColumns();
            for (Column col : baseCols) {
                columnMap.put(col.getColumnName(), col);
            }

            Object[][] cellData = new Object[columnMap.size()][headers.length];
            Set<Entry<String, Column>> entrySet = columnMap.entrySet();
            int row = 0;
            for (Entry<String, Column> entry : entrySet) {
                Column item = entry.getValue();
                int col = 0;
                cellData[row][col++] = item.getColumnName();
                cellData[row][col++] = item.getJdbcTypeName();
                cellData[row][col++] = item.getJavaType();
                cellData[row][col++] = item.getSize();
                cellData[row][col++] = item.isPrimaryKey();

                cellData[row][col++] = item.isUnique();
                cellData[row][col++] = item.isAutoincrement();
                cellData[row][col++] = item.isForeignKey();
                cellData[row][col++] = item.isNullable();
                cellData[row][col++] = item.getDefaultValue();
                cellData[row][col++] = item.isDisplay();
                cellData[row][col++] = item.isSearchable();
                cellData[row][col++] = item.isEditor();
                cellData[row][col++] = item.isSortable();
                cellData[row][col++] = item.getDict();
                cellData[row][col++] = item.getRemarks();
                row++;
            }
            tableGridModel.setDataVector(cellData, headers);
            fitTableColumns(tableGrid, headerWidth);
            btnGenerate.setEnabled(true);
        } catch (Exception e) {
            String message;
            if (e instanceof NullPointerException) {
                message = StringUtils.isNotBlank(e.getMessage()) ? e.getMessage() : "空指针异常";
            } else {
                message = e.getMessage();
            }
            LOGGER.info(e.getMessage(), e);
            JOptionPane.showMessageDialog(this, message, "错误", JOptionPane.ERROR_MESSAGE);
        } finally {
            try {
                if (connection != null) {
                    connection.isReadOnly();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

        }
    }

    /**
     * 代码 生成设置窗口
     */
    private void onGenerateActionPerformed() {
        LoadAotuCodeViewHistory view = new LoadAotuCodeViewHistory(Root.this, configuration, tableModel);
        view.setVisible(true);
        System.gc();
    }

    /**
     * Launch the application.
     */
    public static void main(String[] args) {

        long startTime = System.currentTimeMillis();
        try {

            if (UIManager.getLookAndFeel().isSupportedLookAndFeel()) {
                final String platform = UIManager.getSystemLookAndFeelClassName();
                // If the current Look & Feel does not match the platform Look & Feel,
                // change it so it does.
                if (!UIManager.getLookAndFeel().getName().equals(platform)) {
                    try {
                        UIManager.setLookAndFeel(platform);
                    } catch (Exception exception) {
                        exception.printStackTrace();
                    }
                }
            }
            //这里可以给出一个tip 提示正在启动中....
            LOGGER.info(">>>>>>>启动中....");
            Root frame = new Root();
            frame.setVisible(true);
            //frame.contentSplitPane.setDividerLocation(0.5);
            frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
            LOGGER.info(">>>>>>>启动完成" + (System.currentTimeMillis() - startTime));
        } catch (Exception e) {
            LOGGER.info(e.getMessage(), e);
        }
    }

    class GridCellRenderer extends DefaultTreeCellRenderer {

        private static final long serialVersionUID = -7722773267229736081L;

        @Override
        public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
                                                      boolean leaf, int row, boolean hasFocus) {

            super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);

            if (value instanceof DefaultMutableTreeNode) {
                Object userObject = ((DefaultMutableTreeNode) value).getUserObject();
                setIcon(((TreeNodeData) userObject).getIcon());
            } else {
                setIcon(ImageUtil.createImageIcon("./icon/folder.png"));
            }
            return this;
        }
    }

    class MyTableModelListener implements TableModelListener {
        @Override
        public void tableChanged(TableModelEvent e) {
            if (e.getType() == TableModelEvent.UPDATE && e.getLastRow() >= 0) {
                String columnName = tableGrid.getValueAt(e.getLastRow(), 0).toString();
                String value = tableGrid.getValueAt(e.getLastRow(), e.getColumn()).toString();
                Column column = tableModel.getColumn(columnName);
                if (column != null) {
                    if (e.getColumn() == IDX_COLUMN_JAVATYPE) {
                        column.setJavaType(value);
                    } else if (e.getColumn() == IDX_COLUMN_NULLABLE) {
                        column.setNullable(Boolean.parseBoolean(value));
                    } else if (e.getColumn() == IDX_COLUMN_REMARK) {
                        if (value.equals(column.getRemarks())) return;
                        column.setRemarks(value);
                        TreePath selPath = tablesTree.getSelectionPath();
                        if (selPath == null || selPath.getPath() == null) return;
                        DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) selPath.getPathComponent(1);
                        TreeNodeData nodeData = (TreeNodeData) treeNode.getUserObject();

                        TableUpdateModel updateModel = new TableUpdateModel(tableModel, nodeData.getDatabaseElement());
                        updateModel.setColumnName(columnName);
                        updateModel.setColumnValue(value);
                        updateModel.setType(column.getColumnType());
                        tableChangedMap.put(updateModel.getKey(), updateModel);
                    } else if (e.getColumn() == IDX_COLUMN_DISPLAY) {
                        column.setDisplay(Boolean.parseBoolean(value));
                    } else if (e.getColumn() == IDX_COLUMN_SEARCHABLE) {
                        column.setSearchable(Boolean.parseBoolean(value));
                    } else if (e.getColumn() == IDX_COLUMN_EDITOR) {
                        column.setEditor(Boolean.parseBoolean(value));
                    } else if (e.getColumn() == IDX_COLUMN_SORTABLE) {
                        column.setSortable(Boolean.parseBoolean(value));
                    } else if (e.getColumn() == IDX_COLUMN_DICT) {
                        column.setDict(value);
                    }
                }
            }
        }
    }
}
